#include "wn_update.h"
#include "fcntl.h"
#include "emu_common.h"
#include "wn_protocol.h"
#include "http_download.h"
 #define LOG_TAG              "wn_update"
 #define LOG_LVL              LOG_LVL_DBG
#include <ulog.h>
UPGRADE_PACK g_ota_pack={
        .status = UPGRADE_IDLE,
        .len = 0
};
extern uint8_t ota_downdata[512*1024];
extern int begin_offset;
#define WN_OTA_FILE "/wn_ota.tbl"
int wn_load_fireware(const char *filename)
{
    int fd = open(filename,O_RDONLY);
    int size = 0;
    if(fd >=0)
    {
        int size = read(fd,g_ota_pack.data,sizeof(g_ota_pack.data));
        close(fd);
        printf("read ota packet\n");
        if(size < 0)
        {
            printf("file read failed\n");
            return EMU_ERROR;
        }
        g_ota_pack.len = size;

    }
    else {
        printf("file open failed\n");
        return EMU_ERROR;
    }
    return EMU_SUCCESS;
}
int wn_ota_init()
{
    if(g_ota_pack.len%SUBDEV_PAGE_LEN ==0)
        g_ota_pack.packetCount = g_ota_pack.len/SUBDEV_PAGE_LEN;
    else {
        g_ota_pack.packetCount = g_ota_pack.len/SUBDEV_PAGE_LEN + 1;
    }
    g_ota_pack.packetNo = 0;
}
int wn_ota_start()
{
    g_ota_pack.status = UPGRADE_WORK;
    //开始文件上传
    //char* sn = "";
    int ret = wn_device_startframe(g_ota_pack.current_sn,file_wn_update,g_ota_pack.len,g_ota_pack.packetCount);
    if(ret != EMU_SUCCESS)
    {
        //开始发送失败

    }
    for(int i=0;i<g_ota_pack.packetCount;i++)
    {
        char* data = g_ota_pack.len+g_ota_pack.data_index;
        int len = (g_ota_pack.len-g_ota_pack.data_index)%SUBDEV_PAGE_LEN==0?SUBDEV_PAGE_LEN:(g_ota_pack.len-g_ota_pack.data_index)%SUBDEV_PAGE_LEN;
        ret = wn_device_dataFrame(g_ota_pack.current_sn,file_wn_update,g_ota_pack.packetNo,data,len);
        if(ret == EMU_SUCCESS)
        {
            g_ota_pack.data_index+=len;
            g_ota_pack.packetNo+=1;
        }
        else{
            //重发一次
        }
    }
    //结束上传
    ret = wn_device_stopFrame(g_ota_pack.current_sn,file_wn_update);

    return ret;
}
int wn_ota_getprocess()
{
    return g_ota_pack.data_index*100.0/g_ota_pack.len;
}
int wn_update_process()
{
    int retry = 0;
    //1.读取升级文件
    int ret = wn_load_fireware(WN_OTA_FILE);
    if(ret != EMU_SUCCESS)
    {
        return EMU_ERROR;
    }
    do
    {
        wn_ota_init();
        //PLC组件复位
        rt_thread_delay(3);
        //开始升级
        ret = wn_ota_start();
        if(ret ==EMU_ERROR)
            retry++;
        else {
            return EMU_SUCCESS;
        }
    }while(retry<3);
    return EMU_ERROR;
}

int wn_update_fromurl(const char* url)
{
    int retry = 0;
    //1.下载包
    int ret = http_download_ota(url);
    if(ret != RT_EOK)
    {
        LOG_E("download wn [%s] failed\n",url);
        return EMU_ERROR;
    }
    //2.填充结构体
    rt_memcpy(g_ota_pack.data,ota_downdata,begin_offset);
    g_ota_pack.len = begin_offset;
    LOG_D("wn get pack\n");
    LOG_D("%s",g_ota_pack.data);

    return EMU_ERROR;
    do
    {
        wn_ota_init();
        //PLC组件复位
        rt_thread_delay(3);
        //开始升级
        ret = wn_ota_start();
        if(ret ==EMU_ERROR)
            retry++;
        else {
            return EMU_SUCCESS;
        }
    }while(retry<3);
    return EMU_ERROR;
}
int wn_ota_upgrade(char*url,char* md5,sn_set_t*sns,int sn_size)
{
    //1.下载包
    int ret = http_download_ota(url);
    if(ret != RT_EOK)
    {
        LOG_E("download wn [%s] failed\n",url);
        return EMU_ERROR;
    }
    //2.填充结构体
    rt_memcpy(g_ota_pack.data,ota_downdata,begin_offset);
    g_ota_pack.len = begin_offset;
    LOG_D("wn get pack,begin_offset=%d\n",begin_offset);
    //LOG_D("%s",(char*)g_ota_pack.data);

    return EMU_ERROR;
    for(int i=0;i<sn_size;i++)
    {
        int retry = 0;
        rt_memcpy(g_ota_pack.current_sn,sns[i].sn,sizeof(sns[i].sn));
        do
        {
            wn_ota_init();
            //PLC组件复位
            rt_thread_delay(3);
            //开始升级
            ret = wn_ota_start();
            if(ret ==EMU_ERROR)
                retry++;
            else {
                LOG_D("sn(%s) update success\n",sns[i].sn);
                break;
                //return EMU_SUCCESS;
            }
        }while(retry<3);
        if(retry>=3)
        {
            LOG_D("sn(%s) update failed\n",sns[i].sn);
        }
    }
    return EMU_SUCCESS;
}
typedef struct{
    char url[64];
    char md5[64];
    sn_set_t sns[100];
    int sn_size;
    struct rt_completion comp;
}ota_param_sync_t;
void wn_ota_upgrade_thread(void*param)
{
    ota_param_sync_t* otaParam = param;
    wn_ota_upgrade(otaParam->url,otaParam->md5,otaParam->sns,otaParam->sn_size);
    otaParam->comp.flag = 1;
    LOG_D("finish ota! completion return\n");
    rt_completion_done(&otaParam->comp);
}
int wn_ota_upgrade_async(char*url,char* md5,sn_set_t*sns,int sn_size)
{
    ota_param_sync_t param;
    rt_memset(&param,0,sizeof(ota_param_sync_t));
    rt_strncpy(param.url,url,MIN(sizeof(param.url),rt_strlen(url)));
    rt_strncpy(param.md5,md5,MIN(sizeof(param.md5)-1,rt_strlen(md5)));
    rt_memcpy(param.sns,sns,sizeof(param.sns)*sn_size);
    param.sn_size = sn_size;
    rt_completion_init(&param.comp);
    rt_thread_t tid = rt_thread_create("wn_ota_upgrade", wn_ota_upgrade_thread, &param, 4096, 25,10);
    if(tid != RT_NULL)
    {
        rt_thread_startup(&tid);
    }
    rt_completion_wait(&param.comp,RT_WAITING_FOREVER);
    return param.comp.flag;
}